package com.young.cms.web;

import com.young.cms.model.Column;
import com.young.cms.service.ICmsDBService;
import com.young.cms.model.gen1.Model;
import com.young.cms.model.gen1.ModelAttribute;
import com.young.common.util.Result;
import com.young.common.util.StringUtils;
import com.young.common.core.dal.EDBType;
import com.young.common.core.dal.service.IDataAccessService;
import com.young.interfaces.log.annotation.Log;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;

/**
 * 代码生成服务(old)
 * Created by rookie on 2018/4/2.
 */
@Controller
@RequestMapping(value = "/cms", method = {RequestMethod.GET, RequestMethod.POST})
public class CmsGenerateController {

    @Resource(name = "cmsDBService")
    ICmsDBService dbService;

    @Resource(name = "dataAccessService")
    IDataAccessService dataAccessService;//数据层服务

    private static Logger logger = LoggerFactory.getLogger(CmsGenerateController.class);

    @Log("代码智能生成")
    @RequestMapping("/generate")
    @ResponseBody
    public Object generate(Model model, HttpServletRequest request) throws Exception{
        if (StringUtils.isBlank(model.getPackageName()) || StringUtils.isBlank(model.getModuleName())){
            //包名和模块名不允许为空
            return Result.buildFail("包名和模块名不允许为空");
        }else if (StringUtils.isBlank(model.getTableName())){
            return Result.buildFail("表名不允许为空");
        }else if (StringUtils.isBlank(request.getParameter("rootPath"))){
            return Result.buildFail("请填写正确的存放目录");
        }else{
            //根据表名查询字段信息
            List<Column> list =  dbService.getColumsByTableName(model.getTableName());
            if (list != null && list.size() > 0){
                if (StringUtils.isBlank(model.getClassName())){//类名为空时,自动生成类名
                    String[] arr = model.getTableName().split("_");
                    StringBuilder sb = new StringBuilder();
                    for (int i=0;i<arr.length;i++){
                        sb.append(arr[i].substring(0, 1).toUpperCase()).append(arr[i].substring(1).toLowerCase());//单词首字母大写
                    }
                    model.setClassName(sb.toString());
                }
                //遍历字段,转换为模型类变量
                List<ModelAttribute> attributeList = new ArrayList<ModelAttribute>();
                for (Column column : list){
                    attributeList.add(new ModelAttribute(column));
                }
                model.setAttributeList(attributeList);//设置类的成员变量
                model.setCreateTime(new Date());
                //模板的参数信息
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("model", model);

                //生成文件目录
                String rootPath = request.getParameter("rootPath");//"C:\\Users\\Administrator\\Desktop\\generate";//根目录
                String packagePath = rootPath + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator + model.getPackageName().replace(".", File.separator) + File.separator + model.getModuleName();
                //资源目录,用来放配置文件和mapper文件
                String resourcePath = rootPath + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + model.getPackageName().replace(".", File.separator) + File.separator + model.getModuleName();
                String pagePath = rootPath + File.separator + "src" + File.separator + "main" + File.separator + "webapp" + File.separator + "page" + File.separator + model.getModuleName();//jsp存放目录
                String path_model = packagePath + File.separator + "model";
                String path_service = packagePath + File.separator + "service";
                String path_service_impl = packagePath + File.separator + "service" + File.separator + "impl";
                String path_util = packagePath + File.separator + "util";
                String path_web = packagePath + File.separator + "web";
                String path_mapper;
                if (dataAccessService.getDBType() == EDBType.MYSQL){
                    path_mapper = resourcePath + File.separator + "mapper" + File.separator + "mysql";
                }else if (dataAccessService.getDBType() == EDBType.ORACLE){
                    path_mapper = resourcePath + File.separator + "mapper" + File.separator + "oracle";
                }else if (dataAccessService.getDBType() == EDBType.POSTGRESQL){
                    path_mapper = resourcePath + File.separator + "mapper" + File.separator + "postgres";
                }else {
                    return Result.buildFail("数据库类型不匹配");
                }
                String[] dirs = {path_model, path_service, path_service_impl, path_util, path_web, path_mapper, pagePath};
                //创建各目录
                for(String dir : dirs){
                    File f = new File(dir);
                    if (!f.exists()){//不存在此目录,则创建
                        f.mkdirs();
                        logger.info("[代码生成] 成功创建目录: {}", f.getAbsolutePath());
                    }
                }
                //生成实体类
                Configuration configuration = new Configuration();
                configuration.setClassForTemplateLoading(this.getClass(), "/template/");
                try {
                    Template template = configuration.getTemplate("Model.ftl", "UTF-8");//Locale.CHINA,
                    try {
                        //FileWriter fw = new FileWriter(new File(path_model + File.separator + model.getClassName()+".java"));
                        Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path_model + File.separator + model.getClassName()+".java"), "UTF-8"));
                        template.process(map, fw);
                        fw.flush();
                        fw.close();
                        logger.info("[代码生成] 成功创建实体类: {}", model.getClassName() + ".java");
                    } catch (TemplateException e) {
                        return Result.buildFail("写入文件失败");
                    }
                } catch (IOException e) {
                    return Result.buildFail("获取模板失败");
                }

                //生成Mapper.xml映射文件
                try {
                    Template template = configuration.getTemplate("Mapper.ftl", "UTF-8");//Locale.CHINA,
                    try {
                        //FileWriter fw = new FileWriter(new File(path_mapper + File.separator + model.getClassName()+"Mapper.xml"));
                        Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path_mapper + File.separator + model.getClassName()+"Mapper.xml"), "UTF-8"));
                        template.process(map, fw);
                        fw.flush();
                        fw.close();
                        logger.info("[代码生成] 成功创建Mapper.xml: {}", model.getClassName()+"Mapper.xml");
                    } catch (TemplateException e) {
                        return Result.buildFail("写入文件失败");
                    }
                } catch (IOException e) {
                    return Result.buildFail("获取模板失败");
                }

                //生成service接口
                try {
                    Template template = configuration.getTemplate("Service.ftl", "UTF-8");//Locale.CHINA,
                    try {
                        //FileWriter fw = new FileWriter(new File(path_service + File.separator + "I" + model.getClassName()+"Service.java"));
                        Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path_service + File.separator + "I" + model.getClassName()+"Service.java"), "UTF-8"));
                        template.process(map, fw);
                        fw.flush();
                        fw.close();
                        logger.info("[代码生成] 成功创建service接口: {}", "I" + model.getClassName()+"Service.java");
                    } catch (TemplateException e) {
                        return Result.buildFail("写入文件失败");
                    }
                } catch (IOException e) {
                    return Result.buildFail("获取模板失败");
                }

                //生成serviceImpl服务实现类
                try {
                    Template template = configuration.getTemplate("ServiceImpl.ftl", "UTF-8");//Locale.CHINA,
                    try {
                        //FileWriter fw = new FileWriter(new File(path_service_impl + File.separator + model.getClassName()+"ServiceImpl.java"));
                        Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path_service_impl + File.separator + model.getClassName()+"ServiceImpl.java"), "UTF-8"));
                        template.process(map, fw);
                        fw.flush();
                        fw.close();
                        logger.info("[代码生成] 成功创建service实现类: {}", model.getClassName()+"ServiceImpl.java");
                    } catch (TemplateException e) {
                        return Result.buildFail("写入文件失败");
                    }
                } catch (IOException e) {
                    return Result.buildFail("获取模板失败");
                }

                //生成controller
                try {
                    Template template = configuration.getTemplate("Controller.ftl", "UTF-8");//Locale.CHINA,
                    try {
                        //FileWriter fw = new FileWriter(new File(path_web + File.separator + model.getClassName()+"Controller.java"));
                        Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path_web + File.separator + model.getClassName()+"Controller.java"), "UTF-8"));
                        template.process(map, fw);
                        fw.flush();
                        fw.close();
                        logger.info("[代码生成] 成功创建Controller类: {}", model.getClassName()+"Controller.java");
                    } catch (TemplateException e) {
                        return Result.buildFail("写入文件失败");
                    }
                } catch (IOException e) {
                    return Result.buildFail("获取模板失败");
                }

                //生成视图页
                try {
                    Template template = configuration.getTemplate("List.ftl", "UTF-8");//Locale.CHINA,
                    try {
                        //FileWriter fw = new FileWriter(new File(pagePath + File.separator + model.getClassName().substring(0,1).toLowerCase()+model.getClassName().substring(1) + "List.jsp"));
                        Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pagePath + File.separator + model.getClassName().substring(0,1).toLowerCase()+model.getClassName().substring(1) + "List.jsp"), "UTF-8"));
                        template.process(map, fw);
                        fw.flush();
                        fw.close();
                        logger.info("[代码生成] 成功创建视图页: {}", model.getClassName().substring(0,1).toLowerCase()+model.getClassName().substring(1) + "List.jsp");
                    } catch (TemplateException e) {
                        return Result.buildFail("写入文件失败");
                    }
                } catch (IOException e) {
                    return Result.buildFail("获取模板失败");
                }

                //生成表单页
                try {
                    Template template = configuration.getTemplate("Form.ftl", "UTF-8");//Locale.CHINA,
                    try {
                        //FileWriter fw = new FileWriter(new File(pagePath + File.separator + model.getClassName().substring(0,1).toLowerCase()+model.getClassName().substring(1) + "Form.jsp"));
                        Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pagePath + File.separator + model.getClassName().substring(0,1).toLowerCase()+model.getClassName().substring(1) + "Form.jsp"), "UTF-8"));
                        template.process(map, fw);
                        fw.flush();
                        fw.close();
                        logger.info("[代码生成] 成功创建表单页: {}", model.getClassName().substring(0,1).toLowerCase()+model.getClassName().substring(1) + "Form.jsp");
                    } catch (TemplateException e) {
                        return Result.buildFail("写入文件失败");
                    }
                } catch (IOException e) {
                    return Result.buildFail("获取模板失败");
                }
            }else{
                return Result.buildFail("无效的表信息!");
            }
        }
        return Result.buildSuccess();
    }
}
